package org.mijia.dotsbox.utils;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.MessageFormat;
import java.util.Date;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

import org.mijia.dotsbox.rcp.DotsboxActivator;

public class LogUtils {
    protected static Logger logger;
    protected static boolean bDebug = true;
    
    static class TooSimpleFormatter extends Formatter {
        Date dat = new Date();
        private final static String format = "{0,date} {0,time}";
        private MessageFormat formatter;
        private Object args[] = new Object[1];
        private String lineSeparator = "\n";

        /**
         * Format the given LogRecord.
         * @param record the log record to be formatted.
         * @return a formatted log record
         */
        public synchronized String format(LogRecord record) {
            StringBuffer sb = new StringBuffer();
            // Minimize memory allocations here.
            dat.setTime(record.getMillis());
            args[0] = dat;
            StringBuffer text = new StringBuffer();
            if (formatter == null) {
                formatter = new MessageFormat(format);
            }
            formatter.format(args, text, null);
            sb.append(text);
            sb.append(" ");

            String message = formatMessage(record);
            sb.append(message);
            sb.append(lineSeparator);

            if (record.getThrown() != null) {
                try {
                    StringWriter sw = new StringWriter();
                    PrintWriter pw = new PrintWriter(sw);
                    record.getThrown().printStackTrace(pw);
                    pw.close();
                    sb.append(sw.toString());
                } catch (Exception ex) {
                }
            }
            return sb.toString();
        }
    }
    
    static {
        logger = Logger.getLogger("slojj.dotsbox");
        
        initLogDir();
        try {
            FileHandler handler;
            String filepath = DotsboxActivator.getDefault().getStateLocation()
                    .append("logs/.log").toOSString();
            handler = new FileHandler(filepath);
            handler.setFormatter(new TooSimpleFormatter());
            logger.addHandler(handler);
            logger.setLevel(Level.INFO);
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private static void initLogDir() {
        String filepath = DotsboxActivator.getDefault().getStateLocation()
                .append("logs").toOSString();
        File logDir = new File(filepath);
        if(!logDir.exists() || !logDir.isDirectory())
            logDir.mkdir();
    }
    
    protected static void log(Level level, String message) {
        Thread currentThread = Thread.currentThread();
        StackTraceElement[] sts = currentThread.getStackTrace();
        if (sts != null && sts.length > 4) {
            StackTraceElement ste = sts[4];
            String fileName = ste.getFileName();
            String className = ste.getClassName();
            String methodName = ste.getMethodName();
            int lineNum = ste.getLineNumber();
            
            if(level.equals(Level.SEVERE) || level.equals(Level.WARNING))
                message += " Line:" + lineNum + " File:" + fileName;
            
            LogRecord record = new LogRecord(level, message);
            record.setSourceClassName(className);
            record.setThreadID((int) currentThread.getId());
            record.setSourceMethodName(methodName);
            logger.log(record);
        } else {
            logger.log(level, message);
        }
    }

    public static void error(String message) {
        log(Level.SEVERE, message);
    }

    public static void warning(String message) {
        log(Level.WARNING, message);
    }

    public static void info(String message) {
        log(Level.INFO, message);
    }
    
    public static void debug(String message) {
        if(bDebug) 
            log(Level.INFO, message);
    }
}